package com.zl.tby.service.impl;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.zl.tby.core.base.util.DateTypeEnums;
import com.zl.tby.core.base.util.ToolsUtil;
import com.zl.tby.dto.TbySmartBoxHistoryQuery;
import com.zl.tby.model.TbySmartBoxHistory;
import com.zl.tby.repository.TbySmartBoxHistoryRepo;
import com.zl.tby.service.ITbySmartBoxHistoryService;
import com.zl.tby.vo.box.SmartBoxDataResult;
import com.zl.tby.vo.box.SmartBoxValues;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.annotation.Tran;
import org.noear.wood.DbContext;
import org.noear.wood.DbTableQuery;
import org.noear.wood.annotation.Db;
import org.noear.wood.utils.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 智能箱历史数据
 * @author changpeng
 * @version 1.0
 * @since 2024/8/6 20:22
 */
@Slf4j
@Component
public class TbySmartBoxHistoryServiceImpl implements ITbySmartBoxHistoryService {

    @Db
    private TbySmartBoxHistoryRepo tbySmartBoxHistoryRepo;
    @Db
    private DbContext db;
    @Inject("${smart-box.data-type}")
    private String dataType;
    @Inject("${smart-box.temperature}")
    private String temperature;
    @Inject("${smart-box.humidity}")
    private String humidity;
    @Inject("${smart-box.voltage}")
    private String voltage;
    @Inject("${smart-box.current}")
    private String current;

    @Override
    @Tran
    public void add(String message) {
        if (message == null || !message.startsWith("{")) {
            return;
        }
        try {
            Gson gson = new Gson();
            SmartBoxDataResult result = gson.fromJson(message, new TypeToken<SmartBoxDataResult>(){}.getType());
            if (StringUtils.isEmpty(result.getType()) || !result.getType().equals(dataType)) {
                return;
            }
            LocalDateTime createTime = LocalDateTime.parse(result.getData().getTimeStamp(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            String createDate = createTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            String currentTemperature = null, temperatureUnit = null;
            String currentHumidity = null, humidityUnit = null;
            String currentVoltage = null, voltageUnit = null;
            String currentCurrent = null, currentUnit = null;
            List<SmartBoxValues> dataList = result.getData().getValues();
            for (SmartBoxValues value : dataList) {
                if (value.getId().equals(temperature)) {
                    currentTemperature = value.getValue();
                    temperatureUnit = value.getUnit();
                } else if (value.getId().equals(humidity)) {
                    currentHumidity = value.getValue();
                    humidityUnit = value.getUnit();
                } else if (value.getId().equals(voltage)) {
                    currentVoltage = value.getValue();
                    voltageUnit = value.getUnit();
                } else if (value.getId().equals(current)) {
                    currentCurrent = value.getValue();
                    currentUnit = value.getUnit();
                }
            }
            TbySmartBoxHistory entity = this.getByDeviceSnAndCreateDate(result.getDeviceSn(), createDate);
            if (entity == null) {
                entity = new TbySmartBoxHistory();
                entity.setCreateTime(createTime);
                entity.setCreateDate(createDate);
                entity.setCreateYear(createTime.format(DateTimeFormatter.ofPattern("yyyy")));
                entity.setCreateMonth(createTime.format(DateTimeFormatter.ofPattern("yyyy-MM")));
                entity.setDeviceSn(result.getDeviceSn());
                entity.setName(result.getName());
                entity.setTemperatureHigh(currentTemperature);
                entity.setTemperatureLow(currentTemperature);
                entity.setTemperatureUnit(temperatureUnit);
                entity.setHumidityHigh(currentHumidity);
                entity.setHumidityLow(currentHumidity);
                entity.setHumidityUnit(humidityUnit);
                entity.setVoltageHigh(currentVoltage);
                entity.setVoltageLow(currentVoltage);
                entity.setVoltageUnit(voltageUnit);
                entity.setCurrentHigh(currentCurrent);
                entity.setCurrentLow(currentCurrent);
                entity.setCurrentUnit(currentUnit);
                tbySmartBoxHistoryRepo.insert(entity, true);
                return;
            }
            entity.setTemperatureHigh(compareValue(entity.getTemperatureHigh(), currentTemperature, "high"));
            entity.setTemperatureLow(compareValue(entity.getTemperatureLow(), currentTemperature, "low"));
            entity.setHumidityHigh(compareValue(entity.getHumidityHigh(), currentHumidity, "high"));
            entity.setHumidityLow(compareValue(entity.getHumidityLow(), currentHumidity, "low"));
            entity.setVoltageHigh(compareValue(entity.getVoltageHigh(), currentVoltage, "high"));
            entity.setVoltageLow(compareValue(entity.getVoltageLow(), currentVoltage, "low"));
            entity.setCurrentHigh(compareValue(entity.getCurrentHigh(), currentVoltage, "high"));
            entity.setCurrentLow(compareValue(entity.getCurrentLow(), currentVoltage, "low"));
            entity.setUpdateTime(createTime);
            tbySmartBoxHistoryRepo.updateById(entity, false);
        } catch (Exception ex) {
            log.error("数据转换异常", ex);
        }
    }

    private String compareValue(String oldValue, String newValue, String type) {
        if (oldValue == null) {
            return newValue;
        } else if (newValue != null) {
            if (type.equals("high")) {
                if (new BigDecimal(oldValue).compareTo(new BigDecimal(newValue)) < 0) {
                    return newValue;
                }
            } else {
                if (new BigDecimal(oldValue).compareTo(new BigDecimal(newValue)) > 0) {
                    return newValue;
                }
            }
        }
        return oldValue;
    }

    @Override
    public TbySmartBoxHistory getByDeviceSnAndCreateDate(Long deviceSn, String createDate) {
        List<TbySmartBoxHistory> dataList = tbySmartBoxHistoryRepo.selectList(mapperWhereQ -> {
            mapperWhereQ.whereEq("device_sn", deviceSn).andEq("create_date", createDate);
        });
        return dataList.size() > 0 ? dataList.get(0) : null;
    }

    @Override
    public List<TbySmartBoxHistory> statisticList(TbySmartBoxHistoryQuery query) {
        List<TbySmartBoxHistory> resultList = new ArrayList<>();
        DateTypeEnums dateTypeEnums = DateTypeEnums.getDateType(query.getCreateDateBegin(), query.getCreateDateEnd());
        DbTableQuery tableQuery = db.table("tby_smart_box_history").whereTrue()
                .andIf(query.getDeviceSn() != null, "device_sn = ?", query.getDeviceSn())
                .andIf(StringUtils.isNotEmpty(query.getCreateDateBegin()), "create_time >= ?", ToolsUtil.dateString2Util(query.getCreateDateBegin() + " 00:00:00", "yyyy-MM-dd HH:mm:ss"))
                .andIf(StringUtils.isNotEmpty(query.getCreateDateEnd()), "create_time <= ?", ToolsUtil.dateString2Util(query.getCreateDateEnd() + " 23:59:59", "yyyy-MM-dd HH:mm:ss"));
        tableQuery.groupBy(dateTypeEnums.getColumn()).orderBy(dateTypeEnums.getColumn());
        String selectColumn = dateTypeEnums.getColumn() + """
                    create_date_format, max(temperature_high) temperature_high, min(temperature_low) temperature_low, 
                    max(humidity_high) humidity_high, min(humidity_low) humidity_low,
                    max(voltage_high) voltage_high, min(voltage_low) voltage_low,
                    max(current_high) current_high, min(current_low) current_low
                """;
        try {
            List<TbySmartBoxHistory> dataList = tableQuery.selectList(selectColumn, TbySmartBoxHistory.class);
            Map<String, TbySmartBoxHistory> dataMap = new HashMap<>(0);
            for (TbySmartBoxHistory data : dataList) {
                dataMap.put(data.getCreateDateFormat(), data);
            }
            List<String> xAxisList = dateTypeEnums.getXAxis(query.getCreateDateBegin(), query.getCreateDateEnd());
            for (String s : xAxisList) {
                resultList.add(dataMap.containsKey(s) ? dataMap.get(s) : TbySmartBoxHistory.createEmpty(s));
            }
        } catch (Exception ex) {
            log.error("查询数据统计异常", ex);
        }
        return resultList;
    }
}
